﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD.Core {


    /// <summary>
    /// シェーダー変数宣言をあらわす構造体
    /// </summary>
    /// <remarks>
    /// シェーダー変数宣言とはシェーダー プログラム中で宣言された <c>Uniform</c> 変数と <c>Attribute</c> 変数の事を指します
    /// (両方共通で使用します)。
    /// <see cref="Name"/> は宣言された変数の名前で､<see cref="ComponentType"/>が型を示します｡
    /// <see cref="ArrayLength"/>は配列の場合のみ有効で､配列の要素数を示します｡スカラー型の場合は必ず1が返ります｡
    /// <see cref="Location"/> はその変数にアクセスする場合の場所を示します｡ロケーションは内部的に処理されるので
    /// ユーザーが使用する事はありません｡<see cref="Index"/>は識別の為の一意なインデックスです｡
    /// 内部的に処理されるのでユーザーが使用する事はありません。
    /// <see cref="ShaderDeclaration"/> オブジェクトはユーザーが直接インスタンス化する事はできません。
    /// 必ずエンジン側が作成したものを戻り値で受け取ります。
    /// 宣言された <c>Attribute</c> 変数を取得するには <see cref="ShaderProgram.Attributes"/> を使用します｡
    /// 宣言された <c>Uniform</c> 変数を取得するには <see cref="ShaderProgram.Uniforms"/> を使用します｡
    /// どちらもコンパイル&リンクするまでは取得できません｡
    /// <note type="tip">
    /// ロケーション(<see cref="Location"/>)とインデックス(<see cref="Index"/>)は異なる概念です｡
    /// とはいえ内部的に処理されるので特に気にする必要はありません｡
    /// 詳しくは OpenGL の本を参照してください｡ 
    /// </note>
    /// </remarks>
    /// <seealso cref="ShaderProgram"/>
    /// <seealso cref="ShaderVariableType"/>
    /// <seealso cref="AttributeVariable"/>
    /// <seealso cref="UniformVariable"/>
    public struct ShaderDeclaration {
        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="name">変数名</param>
        /// <param name="type">シェーダー変数の型</param>
        /// <param name="arrayLength">配列の要素数(スカラーの場合は1)</param>
        /// <param name="location">ロケーション</param>
        /// <param name="index">インデックス</param>
        internal ShaderDeclaration (string name, ShaderVariableType type, int arrayLength, int location, int index)
            : this () {
            this.Name = name;
            this.Type = type;
            this.ArrayLength = arrayLength;
            this.Location = location;
            this.Index = index;
        }

        /// <summary>
        /// 変数名
        /// </summary>
        /// <remarks>
        /// 宣言された変数の名前｡大文字小文字を厳密に判定します。
        /// </remarks>
        public string Name { get; private set; }

        /// <summary>
        /// 変数の型
        /// </summary>
        /// <remarks>
        /// <see cref="ShaderVariableType"/> 列挙型の中から該当する1つを返します｡
        /// OpenGL で定義された型のすべてをDDDで扱えるわけではありません｡
        /// </remarks>
        public ShaderVariableType Type { get; private set; }

        /// <summary>
        /// 配列の要素数
        /// </summary>
        /// <remarks>
        /// 宣言された変数がスカラー型の場合は1が返ります｡
        /// </remarks>
        public int ArrayLength { get; private set; }

        /// <summary>
        /// ロケーション
        /// </summary>
        /// <remarks>
        /// 宣言された変数の位置情報です｡ 
        /// OpenGL でシェーダーにデータを転送する時に使用しますが、ユーザーが気にする必要はありません。
        /// </remarks>
        public int Location { get; private set; }

        /// <summary>
        /// 変数インデックス
        /// </summary>
        /// <remarks>
        /// 宣言された変数の一意なインデックスです｡
        /// OpenGL でシェーダーにデータを転送する時に使用しますが、ユーザーが気にする必要はありません。
        /// </remarks>
        public int Index { get; private set; }

        /// <inheritdoc/>
        public override string ToString () {
            return string.Format("{1}", Name);
        }
    }
}
